package com.hjx.windowtool.bk.dibaqu;


import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.table.TableRowSorter;

import org.springframework.data.domain.Page;

import com.hjx.windowtool.bk.dibaqu.server.BookApplication;
import com.hjx.windowtool.bk.dibaqu.server.BookChapter;
import com.hjx.windowtool.bk.dibaqu.server.BookChapterRepository;
import com.hjx.windowtool.bk.dibaqu.server.BookInfo;
import com.hjx.windowtool.bk.dibaqu.server.BookInfoRepository;
import com.hjx.windowtool.bk.dibaqu.server.BookInfoService;
import com.hjx.windowtool.bk.dibaqu.server.ContextUtil;
import com.hjx.windowtool.db.Tool;
import com.hjx.windowtool.tablemodel.TableModel;
import com.hjx.windowtool.util.MyAppender;
import com.hjx.windowtool.util.XiaoshuoDibaquDownloadTest;

import lombok.extern.slf4j.Slf4j;

import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.awt.event.ActionEvent;
import javax.swing.JLabel;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;

@Slf4j
@Tool("数据下载")
public class DibaquBookListApp {

	private static final int PAGE_SIZE = 100;
	private JFrame frame;
	private JTable table;
	private TableModel model;
	private BookInfoRepository bookInfoRepository;
	private BookInfoService bookInfoService;
	private JLabel lbl_size;
	private JLabel lbl_total;
	private JButton btn_download;
	private JTextArea txt_msg;
	private JTextField txt_name;
	private JTextField txt_count;
	private JTextField txt_author;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
					DibaquBookListApp window = new DibaquBookListApp();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public DibaquBookListApp() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 300);
		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		frame.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				int r = JOptionPane.showConfirmDialog(frame, "是否退出？");
				if (0==r) {
					frame.setVisible(false);
					frame.dispose();
					BookApplication.stop();
				}
			}
		});
		
		JPanel panel = new JPanel();
		frame.getContentPane().add(panel, BorderLayout.NORTH);
		
		btn_download = new JButton("下载");
		btn_download.setEnabled(false);
		btn_download.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				log.info("{}",bookInfoService);
				if(bookInfoService==null) {
					return;
				}
				int dialog = JOptionPane.showConfirmDialog(frame, "是否确认重新更新书籍");
				if (0!=dialog) {
					return;
				}
				btn_download.setEnabled(false);
				download();
			}
		});
		
		JLabel label_1 = new JLabel("名称");
		panel.add(label_1);
		
		txt_name = new JTextField();
		panel.add(txt_name);
		txt_name.setColumns(10);
		
		JLabel label_2 = new JLabel("数量");
		panel.add(label_2);
		
		txt_count = new JTextField();
		panel.add(txt_count);
		txt_count.setColumns(10);
		
		JButton button = new JButton("查询");
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				refreshTable();
			}
		});
		
		JLabel label_3 = new JLabel("人");
		panel.add(label_3);
		
		txt_author = new JTextField();
		panel.add(txt_author);
		txt_author.setColumns(10);
		panel.add(button);
		panel.add(btn_download);
		
		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
		
		JScrollPane scrollPane = new JScrollPane();
		tabbedPane.addTab("列表", null, scrollPane, null);
		
		model = new TableModel("id,title,chapterCount,url,author,lastUpdate,lastchapter,fullFlag".split(","), "id,名称,数量,地址".split(","),BookInfo.class);
		table = new JTable(model);
		table.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if(e.getClickCount()!=2) {
					return;
				}
				int selectedRow = table.getSelectedRow();
				if (selectedRow<0) {
					return;
				}
				BookInfo b = (BookInfo) model.getList().get(table.convertRowIndexToModel(selectedRow));
				log.info("{}-{}",b.getTitle(),b.getUrl());
				List<BookChapter> info=bookInfoService.findBookChapterById(b.getId());
				b.setChapters(info);
				new ChapterListApp().open(b);
			}
		});
		table.setCellEditor(new DefaultCellEditor(new JTextField()));
		TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
		sorter.setComparator(2, new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1.compareTo(o2);
			}
		});
		
		sorter.setComparator(0, new Comparator<Long>() {
			@Override
			public int compare(Long o1, Long o2) {
				return o1.compareTo(o2);
			}
		});
		
		table.setRowSorter(sorter);
		scrollPane.setViewportView(table);
		
		JScrollPane scrollPane_1 = new JScrollPane();
		tabbedPane.addTab("日志", null, scrollPane_1, null);
		
		txt_msg = new JTextArea();
		scrollPane_1.setViewportView(txt_msg);
		
		JPanel panel_1 = new JPanel();
		FlowLayout flowLayout = (FlowLayout) panel_1.getLayout();
		flowLayout.setVgap(0);
		flowLayout.setAlignment(FlowLayout.LEFT);
		frame.getContentPane().add(panel_1, BorderLayout.SOUTH);
		
		lbl_size = new JLabel("0000000");
		panel_1.add(lbl_size);
		
		JLabel label = new JLabel("/");
		panel_1.add(label);
		
		lbl_total = new JLabel("000000");
		panel_1.add(lbl_total);
		
		JButton button_1 = new JButton("更多");
		button_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(bookInfoService==null) {
					return;
				}
				if(model.getRowCount()<model.getTotalSize()) {
					Page<BookInfo> page = getPage(model.getRowCount()/PAGE_SIZE);
					model.addList(page.getContent());
					model.setTotalSize(page.getTotalElements());
					updateSize();
				}
			}
		});
		panel_1.add(button_1);
		init();
	}

	protected void download() {
		ExecutorService executorService = Executors.newFixedThreadPool(10,new ThreadFactory() {
			@Override
			public Thread newThread(Runnable r) {
				return new Thread(r, "获取数据线程池");
			}
		});
		new Thread(new Runnable() {
			int emptySize=0;
			AtomicInteger size=new AtomicInteger(0);
			public void run() {
				int i =1;
				while (true) {
					try {
						final List<BookInfo> list = XiaoshuoDibaquDownloadTest.getBookList(i);
						log.info("获取第页数据：{}-{}",i,list.size());
						if (list.size() <=0) {
							if(emptySize>3) {
								break;
							}
							emptySize++;
							i++;
							continue;
						}
						emptySize=0;
						Runnable runnable = new Runnable() {
							public void run() {
								for (int j = 0; j < list.size(); j++) {
									BookInfo bookInfo = list.get(j);
									try {
										XiaoshuoDibaquDownloadTest.getChapter(bookInfo);
									} catch (IOException | InterruptedException e) {
										log.error("获取数据:{} 时发生错误",bookInfo.getTitle(),e);
										j--;
										try {
											Thread.sleep(1000);
										} catch (InterruptedException e1) {
											e1.printStackTrace();
										}
										continue;
									}
									try {
										BookInfo info = bookInfoRepository.findByTitleAndAuthor(bookInfo.getTitle(), bookInfo.getAuthor());
										if (info != null) {
											bookInfo.setId(info.getId());
										}
										BookInfo save = bookInfoService.saveBook(bookInfo);
										bookInfo.setId(save.getId());
										
										if (info==null) {
											model.setTotalSize(model.getTotalSize()+1);
											updateSize();
										}
										log.info("获取第{}个数据完成",size.addAndGet(1));
									} catch (Exception e) {
										log.error("保存数据:{} 时发生错误",bookInfo.getTitle(),e);
									}
								}
							}
						};
						executorService.submit(runnable);
						if(list.size()<30) {
							break;
						}
						i++;
						Thread.sleep(1000);
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
					}
				}
				executorService.shutdown();
				log.info("等待任务完成");
				while(!executorService.isTerminated()) {
					
				}
				log.info("数据下载完成");
				btn_download.setEnabled(true);
			}
		}).start();
	}

	private void init() {
		start();
		MyAppender.list.add(new MyAppender.LogCallback() {
			@Override
			public void log(String s) {
				if (txt_msg.getLineCount()>500000) {
					txt_msg.setText("");
				}
				txt_msg.append(s);
			}
		});
	}

	/**
	 * 
	 */
	public void start() {
		new Thread(new Runnable() {
			public void run() {
				try {
					log.info("准备启动服务");
					BookApplication.start(new String[] {});
					bookInfoService = ContextUtil.getBean(BookInfoService.class);
					bookInfoRepository = ContextUtil.getBean(BookInfoRepository.class);
					log.info("服务启动完成:{}",bookInfoService);
					refreshTable();
					btn_download.setEnabled(true);
				} catch (Exception e) {
					log.error("服务启动时发生错误",e);
				}
			}
		}).start();
	}

	private void refreshTable() {
		if(bookInfoService==null) {
			return;
		}
		Page<BookInfo> p = getPage(0);
		
		model.setList(p.getContent());
		model.setTotalSize(p.getTotalElements());
		updateSize();
	}

	/**
	 * @return
	 */
	public Page<BookInfo> getPage(int page) {
		String name = txt_name.getText();
		Integer count = 0;
		try {
			count = Integer.valueOf(txt_count.getText());
		} catch (Exception e) {}
		Page<BookInfo> p = bookInfoService.findBook(page, PAGE_SIZE, name, txt_author.getText(),count);
		return p;
	}

	/**
	 * 
	 */
	public void updateSize() {
		lbl_size.setText(String.valueOf(model.getRowCount()));
		long totalSize = model.getTotalSize();
		if (totalSize<model.getRowCount()) {
			totalSize=model.getRowCount();
		}
		lbl_total.setText(String.valueOf(totalSize));
	}

}
